#ifndef _HTTP_H_
#define _HTTP_H_
#include <string>
#include <map>
#include <net_tool.h>
class HttpRequest {
    private:

        FILE *fp;
        socketinf si;
        std::string uri, url, queryString, method;
        std::map<std::string,std::string> headers;
        std::map<std::string,std::string> parameters;
        void parseHeader();
        void parseParameter(std::string &input);
    public:
        HttpRequest(socketinf);
        ~HttpRequest();
        std::string getURI();
        std::string getHeader(const std::string &name);
        std::string getQueryString();
        std::string getParameter(std::string &name);
        std::string getMethod();

};

class HttpResponse {
    private:
        bool hasSendHeader = false;
        socketinf si;
        int status = 200;
        std::string msg = "OK";
        std::map<std::string,std::string> headers;
        void sendHeaderContext();
    public:
        HttpResponse(socketinf si);
        HttpResponse& setStatus(int code, const char * msg);
        HttpResponse& setHeader(std::string name, std::string value);
        HttpResponse& setContentType(std::string v);
        HttpResponse& setContentLength(ssize_t s);
        /**
         * 直接发送文件响应。
         * 若文件不存在，自动响应404。
         * 若localFile是文件夹，则抛出异常
         * @param request Http请求对象 ，用于实现断点续传
         * @param localFile 本地文件路径
         */
        void sendFile(HttpRequest &request, std::string &localFile, std::string contenttype);
        void sendFile(HttpRequest &request, std::string &localFile);
        void write(const char * data, ssize_t len);
        void write(std::string &data);
        std::string getHeaderContext();
};

class MimeType {
    private:
        static std::map<std::string, std::string> typemap;
    public:
        /**
         * 获取对应文件后缀名的MIME类型
         * @param suffix 文件后缀名（不带.)
         */
        static std::string get(const std::string &suffix);
        /**
         * 设置对应文件后缀名的MIME类型
         * @param suffix 文件后缀名（不带.)
         * @param type MIME类型
         */
        static void set(std::string suffix, std::string type);
};

class HttpController {
    public:
        virtual void service(HttpRequest &request, HttpResponse &response) = 0;
};

#define DECLARE_WEB_CONTROLLER(name) \
namespace controller { \
    class name : public HttpController { \
        void service(HttpRequest &request, HttpResponse &response); \
    }; \
}
#endif